﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
//using Microsoft.Maps.MapControl.WPF;
using System.IO;
using Microsoft.Win32;
using Catfood.Shapefile;

namespace CatfoodShapefileTest
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Canvas bigCanvas = new Canvas();

        public MainWindow()
        {
            InitializeComponent();
        }


        private void LoadShapefile_Clicked(object sender, RoutedEventArgs e)
        {
            string shapeFilePath = @"..\..\TestShapeFiles\FRANCE_DEPARTEMENTS\DEPARTEMENT.SHP";

            myCanvas.Children.Clear();
            bigCanvas.Children.Clear();            


            using (Catfood.Shapefile.Shapefile shapefile = new Catfood.Shapefile.Shapefile(shapeFilePath))
            {
                RectangleD outerRectangle = new RectangleD(0,0,0,0);

                foreach (Catfood.Shapefile.Shape shape in shapefile)
                {
                    RectangleD tmpRect;
                    RenderShapeOnCanvas(shape, myCanvas, out tmpRect);
                    
                    if (outerRectangle.Equals(new RectangleD(0,0,0,0))) 
                        outerRectangle = tmpRect;

                    if (outerRectangle.Left > tmpRect.Left)
                        outerRectangle.Left = tmpRect.Left;
                    if (outerRectangle.Top > tmpRect.Top)
                        outerRectangle.Top = tmpRect.Top;
                    if (outerRectangle.Right < tmpRect.Right)
                        outerRectangle.Right = tmpRect.Right;
                    if (outerRectangle.Bottom < tmpRect.Bottom)
                        outerRectangle.Bottom = tmpRect.Bottom;
                }


                //ScaleTransform scaleTrans = new ScaleTransform();
                //scaleTrans.ScaleX = 0.00002;
                //scaleTrans.ScaleY = 0.00002;
                //TranslateTransform translateTrans = new TranslateTransform();
                //translateTrans.X = 0;//-70000;
                //translateTrans.Y = 0;//-500000;

                //TransformGroup group = new TransformGroup();
                //group.Children.Add(scaleTrans);
                //group.Children.Add(translateTrans);

                //bigCanvas.RenderTransform = group; 


                Console.WriteLine(String.Format("minX: {0}, minY: {1}, maxX: {2}, maxY: {3}", outerRectangle.Left, outerRectangle.Top, outerRectangle.Right, outerRectangle.Bottom));

                PointCollection myPointCollection = new PointCollection();
                myPointCollection.Add(new Point(outerRectangle.Left, outerRectangle.Top));
                myPointCollection.Add(new Point(outerRectangle.Left, outerRectangle.Bottom));
                myPointCollection.Add(new Point(outerRectangle.Right, outerRectangle.Bottom));
                myPointCollection.Add(new Point(outerRectangle.Right, outerRectangle.Top));

                Polygon myPolygon = new Polygon();
                myPolygon.Points = myPointCollection;
                myPolygon.Fill = Brushes.Blue;
                myPolygon.Stroke = Brushes.Black;
                myPolygon.StrokeThickness = 2;


                myCanvas.Children.Add(myPolygon);

                //myCanvas.Children.Add(bigCanvas);

            }
        }

        private void ClearMap_Clicked(object sender, RoutedEventArgs e)
        {
            myCanvas.Children.Clear();
        }



#region Helper Methods
        //private LocationRect RectangleDToLocationRect(RectangleD bBox)
        //{
        //    return new LocationRect(bBox.Top, bBox.Left, bBox.Bottom, bBox.Right);
        //}

        private void RenderShapeOnCanvas(Catfood.Shapefile.Shape shape, Canvas canvas, out RectangleD outerRectangle)
        {
            outerRectangle = new RectangleD(0, 0, 0, 0);

            switch (shape.Type)
            {
                //case ShapeType.Point:
                //    ShapePoint point = shape as ShapePoint;
                //    canvas.Children.Add(new Pushpin()
                //    {
                //        Location = new Location(point.Point.Y, point.Point.X)
                //    });
                //    break;
                //case ShapeType.PolyLine:
                //    ShapePolyLine polyline = shape as ShapePolyLine;
                //    for (int i = 0; i < polyline.Parts.Count; i++)
                //    {
                //        canvas.Children.Add(new MapPolyline()
                //        {
                //            Locations = PointDArrayToLocationCollection(polyline.Parts[i]),
                //            Stroke = new SolidColorBrush(Color.FromArgb(150, 255, 0, 0)
                //            )
                //        });
                //    }
                //    break;
                case ShapeType.Polygon:
                    ShapePolygon polygon = shape as ShapePolygon;
                    if (polygon.Parts.Count > 0)
                    {
                        outerRectangle = GetPolygonOuterRectangle(polygon);

                        //Only render the exterior ring of polygons for now.
                        for (int i = 0; i < polygon.Parts.Count; i++)
                        {
                            //Note that the exterior rings in a ShapePolygon have a Clockwise order
                            if (!IsCCW(polygon.Parts[i]))
                            {
                                Polygon myPolygon = new Polygon();
                                myPolygon.Points = PointDArrayToPointCollection(polygon.Parts[i]);
                                myPolygon.Fill = Brushes.Gray;
                                myPolygon.Stroke = Brushes.Black;
                                myPolygon.StrokeThickness = 1;
                                canvas.Children.Add(myPolygon);

                                //canvas.Children.Add(new MapPolygon()
                                //{
                                //    Locations = PointDArrayToLocationCollection(polygon.Parts[i]),
                                //    Fill = new SolidColorBrush(Color.FromArgb(150, 0, 0, 255)),
                                //    Stroke = new SolidColorBrush(Color.FromArgb(150, 255, 0, 0))
                                //});
                            }
                        }
                    }
                    break;
                //case ShapeType.MultiPoint:
                //    ShapeMultiPoint multiPoint = shape as ShapeMultiPoint;
                //    for (int i = 0; i < multiPoint.Points.Length; i++)
                //    {
                //        canvas.Children.Add(new Pushpin()
                //        {
                //            Location = new Location(multiPoint.Points[i].Y, multiPoint.Points[i].X)
                //        });
                //    }
                //    break;
                default:
                    break;
            }
        }

        private RectangleD GetPolygonOuterRectangle(ShapePolygon polygon)
        {

            PointCollection myPointCollection = new PointCollection();
            double minX = 0;
            double minY = 0;
            double maxX = 0;
            double maxY = 0;

            minX = polygon.Parts[0][0].X;
            minY = polygon.Parts[0][0].Y;

            //find the min X and Y
            for (int i = 0; i < polygon.Parts.Count; i++)
            {
                PointCollection subPoint = PointDArrayToPointCollection(polygon.Parts[i]);
                for (int j = 0; j < subPoint.Count; j++)
                {
                    if (minX > subPoint[j].X)
                        minX = subPoint[j].X;

                    if (minY > subPoint[j].Y)
                        minY = subPoint[j].Y;

                    if (maxX < subPoint[j].X)
                        maxX = subPoint[j].X;

                    if (maxY < subPoint[j].Y)
                        maxY = subPoint[j].Y;
                }
            }

            return new RectangleD(minX, minY, maxX, maxY);
            //Console.WriteLine(String.Format("minX: {0}, minY: {1}, maxX: {2}, maxY: {3}", minX, minY, maxX, maxY));

        }

        private PointCollection PointDArrayToPointCollection(PointD[] points, double minX = 0, double minY = 0)
        {
            PointCollection pointsColl = new PointCollection();
            int numPoints = points.Length;

            //minX: 99226, minY: 6049647, maxX: 1242375, maxY: 7110480
            double newX;
            double newY;

            minX = 99226;
            minY = 6049647;

            for (int i = 0; i < numPoints; i++)
            {
                if (minX != 0)
                    newX = points[i].X - minX;
                else
                    newX = points[i].X;

                if (minY != 0)
                    newY = points[i].Y - minY;
                else
                    newY = points[i].Y;

                pointsColl.Add(new Point(newX, newY));
            }
            return pointsColl;
        }

        //private LocationCollection PointDArrayToLocationCollection(PointD[] points)
        //{
        //    LocationCollection locations = new LocationCollection();
        //    int numPoints = points.Length;
        //    for (int i = 0; i < numPoints; i++)
        //    {
        //        locations.Add(new Location(points[i].Y, points[i].X));
        //    }
        //    return locations;
        //}

        /// <summary>
        /// Determines if the coordinates in an array are in a counter clockwise order.
        /// </summary>
        /// <returns>A boolean indicating if the coordinates are in a counter clockwiseorder</returns>
        public bool IsCCW(PointD[] points)
        {
            int count = points.Length;
            PointD coordinate = points[0];
            int index1 = 0;
            for (int i = 1; i < count; i++)
            {
                PointD coordinate2 = points[i];
                if (coordinate2.Y > coordinate.Y)
                {
                    coordinate = coordinate2;
                    index1 = i;
                }
            }
            int num4 = index1 - 1;
            if (num4 < 0)
            {
                num4 = count - 2;
            }
            int num5 = index1 + 1;
            if (num5 >= count)
            {
                num5 = 1;
            }
            PointD coordinate3 = points[num4];
            PointD coordinate4 = points[num5];


            double num6 = ((coordinate4.X - coordinate.X) * (coordinate3.Y - coordinate.Y)) - ((coordinate4.Y - coordinate.Y) * (coordinate3.X - coordinate.X));
            if (num6 == 0.0)
            {
                return (coordinate3.X > coordinate4.X);
            }
            return (num6 > 0.0);
        }
#endregion

#region event Methods
        private Point startPoint;
        private Point originalPoint;

        private void clipBorder_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            double zoomDirection = e.Delta > 0 ? 1 : -1;
            //zoomDirection *= 0.5;
            double slidingScale = canvasScaleTransform.ScaleX / 2 * zoomDirection;

            canvasScaleTransform.ScaleX = canvasScaleTransform.ScaleY += slidingScale;
            canvasScaleTransform.CenterX = e.GetPosition(clipBorder).X;
            canvasScaleTransform.CenterY = e.GetPosition(clipBorder).Y;
            Console.WriteLine(String.Format("X : {0}\t, Y : {1}",e.GetPosition(clipBorder).X, e.GetPosition(clipBorder).Y));
        }

        private void myCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {

            myCanvas.CaptureMouse();
            startPoint = e.GetPosition(clipBorder);// e.GetPosition(clipBorder);
            //originalPoint = new Point(canvasTranslateTransform.X,  canvasTranslateTransform.Y); //startPoint; // new Point(0, 0);//
            //canvasTranslateTransform.X = 0;
            //canvasTranslateTransform.Y = 0;


        }

        private void myCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (!myCanvas.IsMouseCaptured) return;
            Vector moveVector = startPoint - e.GetPosition(clipBorder);
            //canvasTranslateTransform.X = originalPoint.X - moveVector.X;
            //canvasTranslateTransform.Y = originalPoint.Y - moveVector.Y
            canvasTranslateTransform.X -= moveVector.X;
            canvasTranslateTransform.Y -= moveVector.Y;
            //var t = (TranslateTransform)((TransformGroup)myCanvas.RenderTransform).Children.First(tr => tr is TranslateTransform);
            //Vector v = startPoint - e.GetPosition(myCanvas);
            ////t.X -= v.X;
            ////t.Y -= v.Y;
            startPoint = e.GetPosition(clipBorder);

        }

        private void myCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            myCanvas.ReleaseMouseCapture();
        }


        private void ClearTransform_Clicked(object sender, RoutedEventArgs e)
        {
            //myCanvas.RenderTransform
        }
#endregion



    }
}
